# stock_monitor.py
import time
import logging
import signal
import sys
from datetime import datetime
from typing import List

from config import STOCKS_TO_MONITOR, MONITOR_CONFIG
from stock_parser import stock_parser, StockData
from mail_sender import EmailSender, email_sender
from alert_manager import AlertManager

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('stock_monitor.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

class StockMonitor:
    """股票监控器"""
    
    def __init__(self):
        self.stock_configs = STOCKS_TO_MONITOR
        self.monitor_config = MONITOR_CONFIG
        self.alert_manager = AlertManager()
        self.is_running = True
        
        # 注册信号处理，优雅退出
        signal.signal(signal.SIGINT, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
    
    def signal_handler(self, signum, frame):
        """信号处理函数"""
        logger.info("接收到退出信号，正在关闭监控器...")
        self.is_running = False
    
    def check_stocks(self):
        """检查所有股票"""
        symbols = [config.symbol for config in self.stock_configs]
        
        # 获取股票数据
        raw_data = stock_parser.fetch_stock_data(symbols)
        if not raw_data:
            logger.error("获取股票数据失败")
            return
        
        # 解析股票数据
        stock_data_list = stock_parser.parse_stock_data(raw_data, self.stock_configs)
        if not stock_data_list:
            logger.error("解析股票数据失败")
            return
        
        for stock_data in stock_data_list:
            logger.info(f"{stock_data.name}, {stock_data.current_price}, {stock_data.change_percent}")
        # 检查每只股票
        for stock_data in stock_data_list:
            self._check_single_stock(stock_data)
    
    def _check_single_stock(self, stock_data: StockData):
        """检查单只股票"""
        # 查找对应的配置
        stock_config = next(
            (config for config in self.stock_configs 
             if config.symbol == stock_data.symbol),
            None
        )
        
        if not stock_config:
            logger.warning(f"未找到股票配置: {stock_data.symbol}")
            return
        
        # 检查是否达到报警阈值
        
        alert_threshold = 0.0
        if stock_data.change_percent >= stock_config.up_threshold:
            alert_threshold = stock_config.up_threshold
        elif stock_data.change_percent <= stock_config.down_threshold:
            alert_threshold = stock_config.down_threshold        
        else:
            logger.debug(
                f"{stock_data.name}: {stock_data.change_percent}% "
                f"(阈值: {stock_config.up_threshold}% 或 {stock_config.down_threshold}%"
            )

        if alert_threshold != 0.0:
            logger.info(
                f"{stock_data.name} 涨跌幅达到 {stock_data.change_percent}%, "
                f"超过阈值 {alert_threshold}%"
            )

            # 检查是否应该发送报警（避免重复报警）
            if self.alert_manager.should_alert(stock_data.symbol, stock_data.change_percent):
                # 发送邮件提醒
                success = email_sender.send_alert(
                    stock_name=stock_data.name,
                    stock_symbol=stock_data.symbol,
                    current_price=stock_data.current_price,
                    change_percent=stock_data.change_percent,
                    change_amount=stock_data.change_amount,
                    threshold=alert_threshold
                )
                
                if success:
                    logger.info(f"成功发送 {stock_data.name} 的提醒邮件")
                else:
                    logger.error(f"发送 {stock_data.name} 提醒邮件失败")
            else:
                logger.info(f"{stock_data.name} 已在近期提醒过，跳过本次提醒")
    
    def run(self):
        """运行监控器"""
        logger.info("启动股票监控系统")
        logger.info(f"监控股票数量: {len(self.stock_configs)}")
        logger.info(f"检查间隔: {self.monitor_config.check_interval} 秒")
        
        # 清理旧的报警记录
        self.alert_manager.cleanup_old_records()
        
        cycle_count = 0

        email_sender.send_notification("程序启动")
        
        while self.is_running:
            try:
                cycle_count += 1
                now = datetime.now()
                # now_time = now.hour * 10000 + now.minute * 100 + now.second
                # if now_time >= 150100:
                #     logger.info(f"=== 当前已闭市，程序退出 ===")
                #     break 

                current_time = now.strftime("%Y-%m-%d %H:%M:%S")
                logger.info(f"=== 第 {cycle_count} 次检查 [{current_time}] ===")
                
                # 执行检查
                self.check_stocks()
                
                # 每24小时清理一次旧记录
                if cycle_count % (24 * 3600 // self.monitor_config.check_interval) == 0:
                    self.alert_manager.cleanup_old_records()
                
                # 等待下一次检查
                logger.info(f"等待 {self.monitor_config.check_interval} 秒后再次检查...")
                for _ in range(self.monitor_config.check_interval):
                    if not self.is_running:
                        break
                    time.sleep(1)
                    
            except Exception as e:
                logger.error(f"监控循环发生错误: {e}")
                # 发送错误通知
                email_sender.send_error_notification(str(e))
                
                if self.is_running:
                    logger.info("等待 30 秒后重试...")
                    time.sleep(30)
        
        logger.info("股票监控系统已停止")
        email_sender.send_notification("程序退出")


def main():
    """主函数"""
    monitor = StockMonitor()
    
    try:
        monitor.run()
    except KeyboardInterrupt:
        logger.info("用户中断程序")
    except Exception as e:
        logger.error(f"程序运行错误: {e}")
        email_sender.send_error_notification(str(e))
    finally:
        logger.info("程序退出")


if __name__ == "__main__":
    main()